package com.smartinput.voice.application.service

import org.springframework.stereotype.Service
import org.springframework.beans.factory.annotation.Autowired
import org.slf4j.LoggerFactory
import jakarta.annotation.PostConstruct

@Service
class SpeechRecognitionManager {
    
    private val logger = LoggerFactory.getLogger(SpeechRecognitionManager::class.java)
    
    @Autowired(required = false)
    private var whisperService: WhisperSpeechRecognitionService? = null
    
    @Autowired(required = false)
    private var aliyunService: AliyunSpeechRecognitionService? = null
    
    @Autowired(required = false)
    private var aliyunWebSocketService: AliyunWebSocketSpeechRecognitionService? = null
    
    @Autowired(required = false)
    private var baiduService: BaiduSpeechRecognitionService? = null
    
    private var availableServices = mutableListOf<SpeechRecognitionService>()
    private var currentService: SpeechRecognitionService? = null
    
    @PostConstruct
    fun initialize() {
        logger.info("初始化语音识别服务管理器...")
        
        // 检查并添加可用的语音识别服务
//       whisperService?.let { checkAndAddService("Whisper", it) }
         aliyunService?.let { checkAndAddService("阿里云HTTP", it) }
        //  aliyunWebSocketService?.let { checkAndAddService("阿里云WebSocket", it) }
    //    baiduService?.let { checkAndAddService("百度", it) }
        
        // 选择最优服务
        selectOptimalService()
        
        logger.info("语音识别服务管理器初始化完成，当前使用: ${currentService?.serviceName}")
    }
    
    private fun checkAndAddService(name: String, service: SpeechRecognitionService) {
        if (service.isAvailable()) {
            availableServices.add(service)
            logger.info("语音识别服务可用: $name")
        } else {
            logger.warn("语音识别服务不可用: $name")
        }
    }
    
    private fun selectOptimalService() {
        // 优先级: 阿里云WebSocket > 阿里云HTTP > Whisper > 百度 (WebSocket作为默认服务)
        currentService = availableServices.firstOrNull { it is AliyunWebSocketSpeechRecognitionService }
            ?: availableServices.firstOrNull { it is AliyunSpeechRecognitionService }
            ?: availableServices.firstOrNull { it is WhisperSpeechRecognitionService }
            ?: availableServices.firstOrNull { it is BaiduSpeechRecognitionService }
            ?: availableServices.firstOrNull()
        
        if (currentService == null) {
            logger.error("没有可用的语音识别服务")
        }
    }
    
    private fun selectServiceForRequest(isRealTime: Boolean): SpeechRecognitionService? {
        return if (isRealTime) {
            // 实时模式：优先选择WebSocket服务
            logger.info("选择实时语音识别服务（WebSocket）")
            availableServices.firstOrNull { it is AliyunWebSocketSpeechRecognitionService }
                ?: availableServices.firstOrNull { it is AliyunSpeechRecognitionService }
                ?: availableServices.firstOrNull()
        } else {
            // 普通模式：优先选择HTTP API服务
            logger.info("选择普通语音识别服务（HTTP API）")
            availableServices.firstOrNull { it is AliyunSpeechRecognitionService }
                ?: availableServices.firstOrNull { it is WhisperSpeechRecognitionService }
                ?: availableServices.firstOrNull { it is BaiduSpeechRecognitionService }
                ?: availableServices.firstOrNull()
        }
    }
    
    fun recognizeAudio(audioData: ByteArray, isRealTime: Boolean = false): RecognitionResult {
        return recognizeAudioWithRetry(audioData, 0, isRealTime)
    }
    
    private fun recognizeAudioWithRetry(audioData: ByteArray, retryCount: Int, isRealTime: Boolean = false): RecognitionResult {
        val maxRetries = availableServices.size
        
        // 根据实时性要求选择合适的服务
        val service = selectServiceForRequest(isRealTime) ?: return RecognitionResult(
            text = "",
            confidence = 0.0,
            success = false,
            error = "没有可用的语音识别服务"
        )

        // 防止无限递归
        if (retryCount >= maxRetries) {
            logger.error("已达到最大重试次数 ($maxRetries)，停止重试")
            return RecognitionResult(
                text = "",
                confidence = 0.0,
                success = false,
                error = "所有语音识别服务都失败了"
            )
        }
        
        return try {
            logger.info("使用语音识别服务: ${service.serviceName} (重试次数: $retryCount)")
            val result = service.recognizeAudio(audioData)
            
            if (!result.success) {
                logger.warn("语音识别失败，尝试切换到备用服务")
                switchToBackupService()
                return recognizeAudioWithRetry(audioData, retryCount + 1, isRealTime)
            }
            
            result
        } catch (e: Exception) {
            logger.error("语音识别异常，尝试切换到备用服务", e)
            switchToBackupService()
            return recognizeAudioWithRetry(audioData, retryCount + 1, isRealTime)
        }
    }
    
    private fun switchToBackupService() {
        val currentIndex = availableServices.indexOf(currentService)
        val nextIndex = (currentIndex + 1) % availableServices.size
        
        if (nextIndex != currentIndex) {
            currentService = availableServices[nextIndex]
            logger.info("切换到备用语音识别服务: ${currentService?.serviceName}")
        } else {
            logger.error("没有可用的备用语音识别服务")
        }
    }
    
    fun getCurrentServiceInfo(): ServiceInfo {
        return ServiceInfo(
            serviceName = currentService?.serviceName ?: "无可用服务",
            availableServices = availableServices.map { it.serviceName },
            isAvailable = currentService != null
        )
    }
    
    interface SpeechRecognitionService {
        fun recognizeAudio(audioData: ByteArray): RecognitionResult
        fun isAvailable(): Boolean
        val serviceName: String
    }
    
    data class RecognitionResult(
        val text: String,
        val confidence: Double,
        val success: Boolean,
        val error: String? = null,
        val isFinal: Boolean = true // 是否为最终结果，默认为true（兼容旧代码）
    )
    
    data class ServiceInfo(
        val serviceName: String,
        val availableServices: List<String>,
        val isAvailable: Boolean
    )
} 